/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include "serial.h"
#include "gpio.h"
#include "key.h"
#include <string.h>
#include "adc.h"
#include "adc_dianwei.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
osThreadId defaultTaskHandle;
osThreadId show_menuHandle;
osThreadId show_adcHandle;
osThreadId show_contralHandle;
osThreadId show_timeHandle;
osThreadId show_spiHandle;
osMessageQId key_numHandle;
osTimerId mykeytimerHandle;
osSemaphoreId send_semHandle;
osSemaphoreId receive_semHandle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
uint16_t menu_num = 0;
extern uint8_t enter_num;
extern uint8_t add_num;
extern uint8_t sub_num;
uint16_t adc_value[10] = {0};
extern uint16_t adc_ret;
extern uint8_t adc_end;
/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void const *argument);
void show_menu_func(void const *argument);
void show_adc_func(void const *argument);
void show_contral_func(void const *argument);
void show_time_func(void const *argument);
void show_spi_func(void const *argument);
void mykeytimer_Callback(void const *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);

/* GetTimerTaskMemory prototype (linked to static allocation support) */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize);

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/* USER CODE BEGIN GET_TIMER_TASK_MEMORY */
static StaticTask_t xTimerTaskTCBBuffer;
static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH];

void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize)
{
  *ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer;
  *ppxTimerTaskStackBuffer = &xTimerStack[0];
  *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
  /* place for user code */
}
/* USER CODE END GET_TIMER_TASK_MEMORY */

/**
 * @brief  FreeRTOS initialization
 * @param  None
 * @retval None
 */
void MX_FREERTOS_Init(void)
{
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */
  /* definition and creation of send_sem */
  osSemaphoreDef(send_sem);
  send_semHandle = osSemaphoreCreate(osSemaphore(send_sem), 1);

  /* definition and creation of receive_sem */
  osSemaphoreDef(receive_sem);
  receive_semHandle = osSemaphoreCreate(osSemaphore(receive_sem), 1);

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* Create the timer(s) */
  /* definition and creation of mykeytimer */
  osTimerDef(mykeytimer, mykeytimer_Callback);
  mykeytimerHandle = osTimerCreate(osTimer(mykeytimer), osTimerOnce, NULL);

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* definition and creation of key_num */
  osMessageQDef(key_num, 4, uint16_t);
  key_numHandle = osMessageCreate(osMessageQ(key_num), NULL);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of show_menu */
  osThreadDef(show_menu, show_menu_func, osPriorityNormal, 0, 128);
  show_menuHandle = osThreadCreate(osThread(show_menu), NULL);

  /* definition and creation of show_adc */
  osThreadDef(show_adc, show_adc_func, osPriorityNormal, 0, 128);
  show_adcHandle = osThreadCreate(osThread(show_adc), NULL);

  /* definition and creation of show_contral */
  osThreadDef(show_contral, show_contral_func, osPriorityNormal, 0, 128);
  show_contralHandle = osThreadCreate(osThread(show_contral), NULL);

  /* definition and creation of show_time */
  osThreadDef(show_time, show_time_func, osPriorityNormal, 0, 128);
  show_timeHandle = osThreadCreate(osThread(show_time), NULL);

  /* definition and creation of show_spi */
  osThreadDef(show_spi, show_spi_func, osPriorityIdle, 0, 128);
  show_spiHandle = osThreadCreate(osThread(show_spi), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */
}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief  Function implementing the defaultTask thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const *argument)
{
  /* USER CODE BEGIN StartDefaultTask */

  HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_value, 10);
  /* Infinite loop */
  for (;;)
  {
    if (adc_end == 1)
    {
      adc_end = 0;
      uint32_t sum = 0;
      for (uint8_t i = 0; i < 10; i++)
      {
        sum += adc_value[i];
      }
      adc_ret = sum / 10;

      // 打印平均值
      printf("ADC平均值: %d，%d，%d，%d，%d，%d，%d，%d，%d，%d，%d\r\n", adc_ret,adc_value[0],adc_value[1],
	  adc_value[2],adc_value[3],adc_value[4],adc_value[5],adc_value[6],
	  adc_value[7],adc_value[8],adc_value[9]);

      // 重新启动ADC DMA转换
      HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_value, 10);
    }
    osDelay(500);
  }
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_show_menu_func */
/**
 * @brief Function implementing the show_menu thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_show_menu_func */
void show_menu_func(void const *argument)
{
  /* USER CODE BEGIN show_menu_func */

  /* ����һ��������Ϣ�ı��� */
  /* Infinite loop */
  for (;;)
  {

    switch (menu_num)
    {
    case 0:
      OLED_Clear();
      OLED_ShowString(0, 0, "00ello", OLED_8X16);
      OLED_Update();
      break;
    case 1:
      OLED_Clear();
      OLED_ShowString(0, 16, "11ello", OLED_8X16);
      OLED_Update();
      break;
    case 2:
      OLED_Clear();
      OLED_ShowString(0, 32, "22ello", OLED_8X16);
      OLED_Update();
      break;
    case 3:
      OLED_Clear();
      OLED_ShowString(0, 48, "33ello", OLED_8X16);
      OLED_Update();
      break;
    }

    osDelay(1);
  }
  /* USER CODE END show_menu_func */
}

/* USER CODE BEGIN Header_show_adc_func */
/**
 * @brief Function implementing the show_adc thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_show_adc_func */
void show_adc_func(void const *argument)
{
  /* USER CODE BEGIN show_adc_func */
  vTaskSuspend(NULL);
  /* Infinite loop */
  for (;;)
  {
    vTaskSuspend(show_menuHandle);
    OLED_Clear();
    OLED_ShowString(0, 0, "adc", OLED_8X16);
    OLED_Update();
    osDelay(1);
  }
  /* USER CODE END show_adc_func */
}

/* USER CODE BEGIN Header_show_contral_func */
/**
 * @brief Function implementing the show_contral thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_show_contral_func */
void show_contral_func(void const *argument)
{
  /* USER CODE BEGIN show_contral_func */
  vTaskSuspend(NULL);
  /* Infinite loop */
  for (;;)
  {
    vTaskSuspend(show_menuHandle);
    OLED_Clear();
    OLED_ShowString(0, 0, "contal", OLED_8X16);
    OLED_Update();
    osDelay(1);
  }
  /* USER CODE END show_contral_func */
}

/* USER CODE BEGIN Header_show_time_func */
/**
 * @brief Function implementing the show_time thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_show_time_func */
void show_time_func(void const *argument)
{
  /* USER CODE BEGIN show_time_func */
  vTaskSuspend(NULL);
  /* Infinite loop */
  for (;;)
  {
    vTaskSuspend(show_menuHandle);
    OLED_Clear();
    OLED_ShowString(0, 0, "time", OLED_8X16);
    OLED_Update();
    osDelay(1);
    osDelay(1);
  }
  /* USER CODE END show_time_func */
}

/* USER CODE BEGIN Header_show_spi_func */
/**
 * @brief Function implementing the show_spi thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_show_spi_func */
void show_spi_func(void const *argument)
{
  /* USER CODE BEGIN show_spi_func */
  vTaskSuspend(NULL);
  /* Infinite loop */
  for (;;)
  {
    vTaskSuspend(show_menuHandle);
    OLED_Clear();
    OLED_ShowString(0, 0, "spi", OLED_8X16);
    OLED_Update();
    osDelay(1);
    osDelay(1);
  }
  /* USER CODE END show_spi_func */
}

/* mykeytimer_Callback function */
void mykeytimer_Callback(void const *argument)
{
  /* USER CODE BEGIN mykeytimer_Callback */

  if (HAL_GPIO_ReadPin(enter_GPIO_Port, enter_Pin) == SET)
  {
    switch (menu_num)
    {
    case 0:
      vTaskResume(show_adcHandle);
      break;
    case 1:
      vTaskResume(show_contralHandle);
      break;
    case 2:
      vTaskResume(show_adcHandle);
      break;
    case 3:
      vTaskResume(show_adcHandle);
      break;
    default:
      OLED_Clear();
      OLED_ShowNum(0, 0, 5, 2, OLED_8X16);
    }
  }
  if (HAL_GPIO_ReadPin(add_GPIO_Port, add_Pin) == SET)
  {
    if (menu_num == 3)
      menu_num = 0;
    else
      menu_num++;
  }
  if (HAL_GPIO_ReadPin(sub_GPIO_Port, sub_Pin) == SET)
  {
    if (menu_num == 0)
      menu_num = 3;
    else
      menu_num--;
  }
  printf("menu_num= %d\r\n", menu_num);
  /* USER CODE END mykeytimer_Callback */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */
